import tkinter as tk
from tkinter import ttk, messagebox
import string
import random

class Plugboard:
    """插线板：交换字母对"""
    def __init__(self, pairs):
        self.mapping = {}
        # 初始化字母表（A-Z自映射）
        for c in string.ascii_uppercase:
            self.mapping[c] = c
        # 应用交换对
        for a, b in pairs:
            self.mapping[a] = b
            self.mapping[b] = a

    def map(self, char):
        return self.mapping.get(char, char)

    def get_mapping(self):
        """获取当前插线板配置"""
        used = set()
        pairs = []
        for a, b in self.mapping.items():
            if a != b and a not in used and b not in used:
                pairs.append((a, b))
                used.add(a)
                used.add(b)
        return pairs


class Rotor:
    """转子：包含内部接线、缺口位置、环设置和当前位置"""
    def __init__(self, name, wiring, notch, ring_setting=0, position=0):
        self.name = name
        self.wiring = wiring
        self.notch = notch
        self.ring_setting = ring_setting
        self.position = position
        # 预计算反向映射
        self.rev_wiring = "".join(chr(65 + wiring.index(chr(i + 65))) for i in range(26))

    def is_at_notch(self):
        """检查当前是否在缺口位置"""
        return self.position == (ord(self.notch) - 65 - self.ring_setting) % 26

    def rotate(self):
        """转动转子：位置+1（模26）"""
        self.position = (self.position + 1) % 26
        return self.position

    def forward_map(self, char_in):
        """正向映射（键盘 -> 反射器）"""
        # 计算接触点：输入+当前位置-环设置
        contact_in = (char_in + self.position - self.ring_setting) % 26
        # 通过内部接线
        char_out = self.wiring[contact_in]
        # 计算输出：字母转索引-当前位置+环设置
        return (ord(char_out) - 65 - self.position + self.ring_setting) % 26

    def backward_map(self, char_in):
        """反向映射（反射器 -> 键盘）"""
        contact_in = (char_in + self.position - self.ring_setting) % 26
        char_out = self.rev_wiring[contact_in]
        return (ord(char_out) - 65 - self.position + self.ring_setting) % 26

    def get_position_char(self):
        """获取当前位置的字母表示"""
        return chr(self.position + 65)
    
    def get_ring_setting_char(self):
        """获取环设置的字母表示"""
        return chr(self.ring_setting + 65)


class Reflector:
    """反射器：固定字母映射"""
    def __init__(self, name, wiring):
        self.name = name
        self.wiring = wiring

    def map(self, char_in):
        return ord(self.wiring[char_in]) - 65


class EnigmaMachine:
    """恩尼格玛机：整合插线板、转子、反射器"""
    def __init__(self, plugboard_pairs, rotor_types, ring_settings, initial_positions, reflector_type="B"):
        # 初始化组件
        self.plugboard = Plugboard(plugboard_pairs)
        
        # 转子配置（I-V型）
        rotor_specs = {
            "I": ("EKMFLGDQVZNTOWYHXUSPAIBRCJ", "Q"),
            "II": ("AJDKSIRUXBLHWTMCQGZNPYFVOE", "E"),
            "III": ("BDFHJLCPRTXVZNYEIWGAKMUSQO", "V"),
            "IV": ("ESOVPZJAYQUIRHXLNFTGKDCMWB", "J"),
            "V": ("VZBRGITYUPSDNHLXAWMJQOFECK", "Z")
        }
        
        self.rotors = [
            Rotor(rt, rotor_specs[rt][0], rotor_specs[rt][1], rs, pos)
            for rt, rs, pos in zip(rotor_types, ring_settings, initial_positions)
        ]
        
        # 反射器配置
        reflector_wirings = {
            "B": "YRUHQSLDPXNGOKMIEBFZCWVJAT",
            "C": "FVPJIAOYEDRZXWGCTKUQSBNMHL"
        }
        self.reflector = Reflector(reflector_type, reflector_wirings[reflector_type])
        
        # 转动标志（用于双步进机制）
        self.next_turn = [False] * (len(rotor_types))
        
        # 保存初始状态用于重置
        self.initial_positions = initial_positions.copy()
        self.initial_ring_settings = ring_settings.copy()

    def _step_rotors(self):
        """模拟转子转动机制（含双步进）"""
        # 最右转子总是转动
        self.rotors[0].rotate()
        
        # 检查转动标志（从上一次按键传递）
        for i in range(1, len(self.rotors)):
            if self.next_turn[i - 1]:
                self.rotors[i].rotate()
        
        # 更新下一次的转动标志：检查当前转子是否在缺口位置
        for i in range(len(self.rotors) - 1):
            self.next_turn[i] = self.rotors[i].is_at_notch()

    def encrypt_char(self, char):
        """加密单个字符"""
        if not char.isalpha():
            return char
        
        # 步骤1: 转子转动
        self._step_rotors()
        
        # 步骤2: 大写转换
        char = char.upper()
        
        # 步骤3: 通过插线板
        char = self.plugboard.map(char)
        num = ord(char) - 65
        
        # 步骤4: 正向通过转子（右->左）
        for rotor in self.rotors:
            num = rotor.forward_map(num)
        
        # 步骤5: 通过反射器
        num = self.reflector.map(num)
        
        # 步骤6: 反向通过转子（左->右）
        for rotor in reversed(self.rotors):
            num = rotor.backward_map(num)
        
        # 步骤7: 通过插线板（返回）
        char = chr(num + 65)
        char = self.plugboard.map(char)
        return char

    def encrypt(self, text):
        """加密文本"""
        return "".join(self.encrypt_char(c) for c in text)
    
    def decrypt(self, text):
        """解密文本（恩尼格玛机是对称的，解密只需重置位置并再次加密）"""
        self.reset()
        return self.encrypt(text)
    
    def reset(self):
        """重置转子位置到初始状态"""
        for i, rotor in enumerate(self.rotors):
            rotor.position = self.initial_positions[i]
            rotor.ring_setting = self.initial_ring_settings[i]
        self.next_turn = [False] * len(self.rotors)
    
    def get_rotor_positions(self):
        """获取当前转子位置（字母表示）"""
        return [rotor.get_position_char() for rotor in self.rotors]
    
    def get_rotor_ring_settings(self):
        """获取转子环设置（字母表示）"""
        return [rotor.get_ring_setting_char() for rotor in self.rotors]
    
    def get_plugboard_mapping(self):
        """获取插线板配置"""
        return self.plugboard.get_mapping()


class EnigmaApp:
    """恩尼格玛密码机图形界面"""
    def __init__(self, root):
        self.root = root
        self.root.title("恩尼格玛密码机模拟器")
        self.root.geometry("900x650")
        self.root.configure(bg="#2c3e50")
        
        # 创建恩尼格玛机实例
        self.enigma = self.create_default_enigma()
        
        # 创建UI
        self.create_widgets()
        self.update_rotor_display()
        self.update_plugboard_display()
    
    def create_default_enigma(self):
        """创建默认配置的恩尼格玛机"""
        plugboard_pairs = [('A', 'B'), ('C', 'D'), ('E', 'F')]
        rotor_types = ["I", "II", "III"]
        ring_settings = [0, 0, 0]
        initial_positions = [0, 0, 0]
        return EnigmaMachine(plugboard_pairs, rotor_types, ring_settings, initial_positions)
    
    def create_widgets(self):
        """创建界面组件"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 标题
        title = ttk.Label(main_frame, text="恩尼格玛密码机", font=("Arial", 24, "bold"), foreground="#3498db")
        title.pack(pady=10)
        
        # 创建标签页
        notebook = ttk.Notebook(main_frame)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 加密/解密标签页
        crypto_frame = ttk.Frame(notebook, padding=10)
        notebook.add(crypto_frame, text="加密/解密")
        
        # 配置标签页
        config_frame = ttk.Frame(notebook, padding=10)
        notebook.add(config_frame, text="机器配置")
        
        # 转子位置标签页
        rotor_frame = ttk.Frame(notebook, padding=10)
        notebook.add(rotor_frame, text="转子位置")
        
        # 构建加密/解密标签页
        self.build_crypto_tab(crypto_frame)
        
        # 构建配置标签页
        self.build_config_tab(config_frame)
        
        # 构建转子位置标签页
        self.build_rotor_tab(rotor_frame)
    
    def build_crypto_tab(self, parent):
        """构建加密/解密标签页"""
        # 输入框
        input_frame = ttk.LabelFrame(parent, text="输入文本", padding=10)
        input_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.input_text = tk.Text(input_frame, height=6, width=60, font=("Consolas", 12))
        self.input_text.pack(fill=tk.BOTH, expand=True)
        self.input_text.insert("1.0", "HELLO WORLD")
        
        # 按钮框架
        btn_frame = ttk.Frame(parent)
        btn_frame.pack(fill=tk.X, padx=5, pady=10)
        
        encrypt_btn = ttk.Button(btn_frame, text="加密", command=self.encrypt_text)
        encrypt_btn.pack(side=tk.LEFT, padx=10)
        
        decrypt_btn = ttk.Button(btn_frame, text="解密", command=self.decrypt_text)
        decrypt_btn.pack(side=tk.LEFT, padx=10)
        
        reset_btn = ttk.Button(btn_frame, text="重置机器", command=self.reset_machine)
        reset_btn.pack(side=tk.RIGHT, padx=10)
        
        # 输出框
        output_frame = ttk.LabelFrame(parent, text="输出结果", padding=10)
        output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        self.output_text = tk.Text(output_frame, height=6, width=60, font=("Consolas", 12))
        self.output_text.pack(fill=tk.BOTH, expand=True)
        
        # 状态栏
        status_frame = ttk.Frame(parent)
        status_frame.pack(fill=tk.X, padx=5, pady=5)
        
        self.status_var = tk.StringVar(value="就绪")
        status_label = ttk.Label(status_frame, textvariable=self.status_var)
        status_label.pack(side=tk.LEFT)
    
    def build_config_tab(self, parent):
        """构建配置标签页"""
        # 转子配置
        rotor_frame = ttk.LabelFrame(parent, text="转子配置", padding=10)
        rotor_frame.pack(fill=tk.X, padx=5, pady=5)
        
        # 转子选择
        rotor_row1 = ttk.Frame(rotor_frame)
        rotor_row1.pack(fill=tk.X, pady=5)
        
        ttk.Label(rotor_row1, text="右转子:").pack(side=tk.LEFT, padx=5)
        self.rotor1_var = tk.StringVar(value="III")
        rotor1_combo = ttk.Combobox(rotor_row1, textvariable=self.rotor1_var, 
                                   values=["I", "II", "III", "IV", "V"], width=5)
        rotor1_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(rotor_row1, text="中转子:").pack(side=tk.LEFT, padx=10)
        self.rotor2_var = tk.StringVar(value="II")
        rotor2_combo = ttk.Combobox(rotor_row1, textvariable=self.rotor2_var, 
                                   values=["I", "II", "III", "IV", "V"], width=5)
        rotor2_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(rotor_row1, text="左转子:").pack(side=tk.LEFT, padx=10)
        self.rotor3_var = tk.StringVar(value="I")
        rotor3_combo = ttk.Combobox(rotor_row1, textvariable=self.rotor3_var, 
                                   values=["I", "II", "III", "IV", "V"], width=5)
        rotor3_combo.pack(side=tk.LEFT, padx=5)
        
        # 环设置
        ring_row = ttk.Frame(rotor_frame)
        ring_row.pack(fill=tk.X, pady=5)
        
        ttk.Label(ring_row, text="右环设置:").pack(side=tk.LEFT, padx=5)
        self.ring1_var = tk.StringVar(value="A")
        ring1_combo = ttk.Combobox(ring_row, textvariable=self.ring1_var, 
                                  values=list(string.ascii_uppercase), width=3)
        ring1_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(ring_row, text="中环设置:").pack(side=tk.LEFT, padx=10)
        self.ring2_var = tk.StringVar(value="A")
        ring2_combo = ttk.Combobox(ring_row, textvariable=self.ring2_var, 
                                  values=list(string.ascii_uppercase), width=3)
        ring2_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(ring_row, text="左环设置:").pack(side=tk.LEFT, padx=10)
        self.ring3_var = tk.StringVar(value="A")
        ring3_combo = ttk.Combobox(ring_row, textvariable=self.ring3_var, 
                                  values=list(string.ascii_uppercase), width=3)
        ring3_combo.pack(side=tk.LEFT, padx=5)
        
        # 反射器配置
        reflector_frame = ttk.LabelFrame(parent, text="反射器配置", padding=10)
        reflector_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(reflector_frame, text="反射器类型:").pack(side=tk.LEFT, padx=5)
        self.reflector_var = tk.StringVar(value="B")
        reflector_combo = ttk.Combobox(reflector_frame, textvariable=self.reflector_var, 
                                     values=["B", "C"], width=5)
        reflector_combo.pack(side=tk.LEFT, padx=5)
        
        # 插线板配置
        plugboard_frame = ttk.LabelFrame(parent, text="插线板配置", padding=10)
        plugboard_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 插线板显示区域
        self.plugboard_canvas = tk.Canvas(plugboard_frame, height=150, bg="white")
        self.plugboard_canvas.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 插线板控制
        plug_control_frame = ttk.Frame(plugboard_frame)
        plug_control_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(plug_control_frame, text="添加连接:").pack(side=tk.LEFT, padx=5)
        
        self.plug1_var = tk.StringVar()
        plug1_combo = ttk.Combobox(plug_control_frame, textvariable=self.plug1_var, 
                                  values=list(string.ascii_uppercase), width=3)
        plug1_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(plug_control_frame, text="↔").pack(side=tk.LEFT, padx=5)
        
        self.plug2_var = tk.StringVar()
        plug2_combo = ttk.Combobox(plug_control_frame, textvariable=self.plug2_var, 
                                  values=list(string.ascii_uppercase), width=3)
        plug2_combo.pack(side=tk.LEFT, padx=5)
        
        add_btn = ttk.Button(plug_control_frame, text="添加", command=self.add_plug)
        add_btn.pack(side=tk.LEFT, padx=10)
        
        clear_btn = ttk.Button(plug_control_frame, text="清除全部", command=self.clear_plugs)
        clear_btn.pack(side=tk.RIGHT, padx=10)
        
        # 应用配置按钮
        apply_btn = ttk.Button(parent, text="应用配置", command=self.apply_config)
        apply_btn.pack(pady=10)
    
    def build_rotor_tab(self, parent):
        """构建转子位置标签页"""
        # 转子位置显示
        rotor_display_frame = ttk.LabelFrame(parent, text="当前转子位置", padding=10)
        rotor_display_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        self.rotor_canvas = tk.Canvas(rotor_display_frame, bg="#ecf0f1", height=200)
        self.rotor_canvas.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 转子位置控制
        rotor_control_frame = ttk.Frame(parent)
        rotor_control_frame.pack(fill=tk.X, padx=5, pady=5)
        
        ttk.Label(rotor_control_frame, text="右转子位置:").pack(side=tk.LEFT, padx=5)
        self.rotor_pos1_var = tk.StringVar(value="A")
        rotor_pos1_combo = ttk.Combobox(rotor_control_frame, textvariable=self.rotor_pos1_var, 
                                       values=list(string.ascii_uppercase), width=3)
        rotor_pos1_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(rotor_control_frame, text="中转子位置:").pack(side=tk.LEFT, padx=10)
        self.rotor_pos2_var = tk.StringVar(value="A")
        rotor_pos2_combo = ttk.Combobox(rotor_control_frame, textvariable=self.rotor_pos2_var, 
                                       values=list(string.ascii_uppercase), width=3)
        rotor_pos2_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(rotor_control_frame, text="左转子位置:").pack(side=tk.LEFT, padx=10)
        self.rotor_pos3_var = tk.StringVar(value="A")
        rotor_pos3_combo = ttk.Combobox(rotor_control_frame, textvariable=self.rotor_pos3_var, 
                                       values=list(string.ascii_uppercase), width=3)
        rotor_pos3_combo.pack(side=tk.LEFT, padx=5)
        
        set_btn = ttk.Button(rotor_control_frame, text="设置位置", command=self.set_rotor_positions)
        set_btn.pack(side=tk.RIGHT, padx=10)
    
    def add_plug(self):
        """添加插线板连接"""
        a = self.plug1_var.get()
        b = self.plug2_var.get()
        
        if not a or not b:
            messagebox.showerror("错误", "请选择两个不同的字母")
            return
        
        if a == b:
            messagebox.showerror("错误", "不能将字母连接到自身")
            return
        
        # 检查字母是否已被使用
        current_pairs = self.enigma.get_plugboard_mapping()
        used_letters = set()
        for pair in current_pairs:
            used_letters.add(pair[0])
            used_letters.add(pair[1])
        
        if a in used_letters or b in used_letters:
            messagebox.showerror("错误", f"字母 {a} 或 {b} 已被使用")
            return
        
        # 添加新连接
        current_pairs.append((a, b))
        self.enigma.plugboard = Plugboard(current_pairs)
        self.update_plugboard_display()
        
        # 清空选择
        self.plug1_var.set("")
        self.plug2_var.set("")
    
    def clear_plugs(self):
        """清除所有插线板连接"""
        self.enigma.plugboard = Plugboard([])
        self.update_plugboard_display()
    
    def apply_config(self):
        """应用配置更改"""
        try:
            # 获取转子类型
            rotor_types = [
                self.rotor1_var.get(),
                self.rotor2_var.get(),
                self.rotor3_var.get()
            ]
            
            # 获取环设置（字母转数字）
            ring_settings = [
                ord(self.ring1_var.get()) - 65,
                ord(self.ring2_var.get()) - 65,
                ord(self.ring3_var.get()) - 65
            ]
            
            # 获取初始位置
            initial_positions = [
                ord(self.rotor_pos1_var.get()) - 65,
                ord(self.rotor_pos2_var.get()) - 65,
                ord(self.rotor_pos3_var.get()) - 65
            ]
            
            # 获取反射器类型
            reflector_type = self.reflector_var.get()
            
            # 获取当前插线板配置
            plugboard_pairs = self.enigma.get_plugboard_mapping()
            
            # 创建新的恩尼格玛机
            self.enigma = EnigmaMachine(
                plugboard_pairs,
                rotor_types,
                ring_settings,
                initial_positions,
                reflector_type
            )
            
            self.update_rotor_display()
            self.status_var.set("配置已更新")
        except Exception as e:
            messagebox.showerror("错误", f"配置错误: {str(e)}")
    
    def set_rotor_positions(self):
        """设置转子位置"""
        try:
            positions = [
                ord(self.rotor_pos1_var.get()) - 65,
                ord(self.rotor_pos2_var.get()) - 65,
                ord(self.rotor_pos3_var.get()) - 65
            ]
            
            for i, pos in enumerate(positions):
                self.enigma.rotors[i].position = pos
            
            self.update_rotor_display()
            self.status_var.set("转子位置已更新")
        except Exception as e:
            messagebox.showerror("错误", f"位置设置错误: {str(e)}")
    
    def encrypt_text(self):
        """加密文本"""
        text = self.input_text.get("1.0", tk.END).strip()
        if not text:
            messagebox.showwarning("警告", "请输入要加密的文本")
            return
        
        try:
            result = self.enigma.encrypt(text)
            self.output_text.delete("1.0", tk.END)
            self.output_text.insert("1.0", result)
            self.status_var.set("文本已加密")
            self.update_rotor_display()
        except Exception as e:
            messagebox.showerror("错误", f"加密失败: {str(e)}")
    
    def decrypt_text(self):
        """解密文本"""
        text = self.input_text.get("1.0", tk.END).strip()
        if not text:
            messagebox.showwarning("警告", "请输入要解密的文本")
            return
        
        try:
            result = self.enigma.decrypt(text)
            self.output_text.delete("1.0", tk.END)
            self.output_text.insert("1.0", result)
            self.status_var.set("文本已解密")
            self.update_rotor_display()
        except Exception as e:
            messagebox.showerror("错误", f"解密失败: {str(e)}")
    
    def reset_machine(self):
        """重置机器到初始状态"""
        self.enigma.reset()
        self.update_rotor_display()
        self.status_var.set("机器已重置")
    
    def update_rotor_display(self):
        """更新转子位置显示"""
        canvas = self.rotor_canvas
        canvas.delete("all")
        
        positions = self.enigma.get_rotor_positions()
        ring_settings = self.enigma.get_rotor_ring_settings()
        rotor_names = [rotor.name for rotor in self.enigma.rotors]
        
        width = canvas.winfo_width()
        if width < 10:
            width = 700
        
        rotor_width = (width - 100) // 3
        start_x = 50
        
        for i in range(3):
            # 转子背景
            x0 = start_x + i * (rotor_width + 20)
            y0 = 30
            x1 = x0 + rotor_width
            y1 = 150
            
            # 转子框
            canvas.create_rectangle(x0, y0, x1, y1, fill="#3498db", outline="#2980b9", width=2)
            
            # 转子标签
            canvas.create_text((x0+x1)//2, 15, text=f"{rotor_names[i]}型转子", 
                              font=("Arial", 10, "bold"), fill="#2c3e50")
            
            # 环设置
            canvas.create_text((x0+x1)//2, y1+10, text=f"环设置: {ring_settings[i]}", 
                              font=("Arial", 9), fill="#2c3e50")
            
            # 位置显示
            canvas.create_rectangle(x0+20, y0+20, x1-20, y0+50, fill="#ecf0f1", outline="#bdc3c7")
            canvas.create_text((x0+x1)//2, y0+35, text=positions[i], 
                              font=("Arial", 16, "bold"), fill="#e74c3c")
        
        # 反射器
        x0 = start_x + 3 * (rotor_width + 20)
        y0 = 30
        x1 = x0 + rotor_width - 40
        y1 = 150
        
        canvas.create_rectangle(x0, y0, x1, y1, fill="#9b59b6", outline="#8e44ad", width=2)
        canvas.create_text((x0+x1)//2, 15, text=f"{self.enigma.reflector.name}型反射器", 
                          font=("Arial", 10, "bold"), fill="#2c3e50")
    
    def update_plugboard_display(self):
        """更新插线板显示"""
        canvas = self.plugboard_canvas
        canvas.delete("all")
        
        pairs = self.enigma.get_plugboard_mapping()
        width = canvas.winfo_width()
        height = canvas.winfo_height()
        
        if width < 10 or height < 10:
            return
        
        # 绘制字母表
        letters = list(string.ascii_uppercase)
        letter_width = width // 26
        
        for i, letter in enumerate(letters):
            x = i * letter_width + letter_width // 2
            y_top = 30
            y_bottom = height - 30
            
            # 顶部字母
            canvas.create_text(x, y_top, text=letter, font=("Arial", 12, "bold"), fill="#2c3e50")
            
            # 底部字母
            canvas.create_text(x, y_bottom, text=letter, font=("Arial", 12, "bold"), fill="#2c3e50")
        
        # 绘制连接线
        for a, b in pairs:
            idx_a = ord(a) - 65
            idx_b = ord(b) - 65
            
            x1 = idx_a * letter_width + letter_width // 2
            x2 = idx_b * letter_width + letter_width // 2
            
            # 创建曲线连接
            mid_x = (x1 + x2) // 2
            mid_y = height // 2
            
            canvas.create_line(x1, 40, mid_x, mid_y, x2, 40, 
                              fill="#e74c3c", width=2, smooth=True)
            
            # 在连接点添加圆圈
            canvas.create_oval(x1-10, 30, x1+10, 50, fill="#3498db", outline="#2980b9")
            canvas.create_oval(x2-10, 30, x2+10, 50, fill="#3498db", outline="#2980b9")
            
            # 显示字母
            canvas.create_text(x1, 40, text=a, font=("Arial", 10, "bold"), fill="white")
            canvas.create_text(x2, 40, text=b, font=("Arial", 10, "bold"), fill="white")


if __name__ == "__main__":
    root = tk.Tk()
    app = EnigmaApp(root)
    root.mainloop()